﻿using Abp.Domain.Repositories;
using Abp.Domain.Services;
using Abp.Domain.Uow;
using Mt.Site.Core.ContentManagement.Entities;
using Mt.Site.Core.StaticPages;
using Mt.Site.Core.Storage;
using Mt.Site.Core.Synchronization.Data;
using System;
using System.Threading.Tasks;

namespace Mt.Site.Core.Synchronization.ContentManagement
{
    public class ContentAutoSyncManager : DomainService, IContentAutoSyncManager
    {
        private readonly IRepository<Content, Guid> _contentRepository;

        private readonly ISynchronizationHelper _synchronizationHelper;

        private readonly IContentDataSoreManager _contentDataSoreManager;

        private readonly IRepository<FileObject, Guid> _fileObjectRepository;

        private readonly IStaticPageHelper _staticPageHelper;

        public ContentAutoSyncManager(
                IRepository<Content, Guid> contentRepository,
                ISynchronizationHelper synchronizationHelper,
                IContentDataSoreManager contentDataSoreManager,
                IRepository<FileObject, Guid> fileObjectRepository,
                IStaticPageHelper staticPageHelper)
        {
            _contentRepository = contentRepository;
            _synchronizationHelper = synchronizationHelper;
            _contentDataSoreManager = contentDataSoreManager;
            _fileObjectRepository = fileObjectRepository;
            _staticPageHelper = staticPageHelper;
        }

        [UnitOfWork]
        public async Task<Guid> CreateOrUpdateContentSync(CreateOrUpdateSynchorizeStore input)
        {
            using (CurrentUnitOfWork.DisableFilter(
                AbpDataFilters.MayHaveTenant,
                AbpDataFilters.MustHaveTenant,
                MtSiteConsts.AbpDataFilters.MustHaveLanguage,
                AbpDataFilters.SoftDelete))
            {
                var notifyArgs = new NoticeArgs();
                try
                {
                    var syncInfo = ContentSyncHelper.CheckDataStatusAndSyncForAutoSync(
                        _contentRepository, _synchronizationHelper, _contentDataSoreManager, _staticPageHelper,
                        input.ToTenantId, input.TargetLanguage, input.Id, notifyArgs);
                    notifyArgs.Type = input.OptionType;
                    if (syncInfo != null && syncInfo.ToId != Guid.Empty)
                    {
                        _synchronizationHelper.SyncRouteStr(input.Id, syncInfo.ToId, input.ToTenantId, input.TargetLanguage);
                        await _synchronizationHelper.SendNoticeForSuccessAsync(notifyArgs);
                        return syncInfo.ToId;
                    }
                    return Guid.Empty;
                }
                catch (Exception ex)
                {
                    Logger.Error("内容自动同步出错:", ex);
                    if (notifyArgs.FromId != Guid.Empty)
                    {
                        await _synchronizationHelper.SendNoticeForFailAsync(notifyArgs);
                    }
                    throw;
                }
            }
        }

        [UnitOfWork]
        public async Task<Guid> DeleteContentSync(DeleteSyncStore input)
        {
            using (CurrentUnitOfWork.DisableFilter(
                AbpDataFilters.MayHaveTenant,
                AbpDataFilters.MustHaveTenant,
                MtSiteConsts.AbpDataFilters.MustHaveLanguage,
                AbpDataFilters.SoftDelete))
            {
                var notifyArgs = new NoticeArgs();
                try
                {
                    var syncInfo = ContentSyncHelper.CheckDataStatusForAutoSync(_contentRepository, _synchronizationHelper, 
                        input.ToTenantId, input.TargetLanguage, input.Id, notifyArgs);
                    notifyArgs.Type = input.OptionType;
                    if (syncInfo == null || syncInfo.ToId == Guid.Empty)
                    {
                        return Guid.Empty;
                    }

                    _staticPageHelper.DeleteListAndDetailPage(input.ToTenantId, input.TargetLanguage, syncInfo.ToMenuId, syncInfo.ToAuxiliaryId);
                    await _fileObjectRepository.DeleteAsync(
                            item => item.ContentId == syncInfo.ToId && item.Language == input.TargetLanguage && item.TenantId == input.ToTenantId);
                    await _contentRepository.DeleteAsync(syncInfo.ToId);
                    await _synchronizationHelper.DeleteSyncRouteAsync(syncInfo.ToId, input.ToTenantId);
                    _synchronizationHelper.DeleteSeo(syncInfo.ToId);
                    await _synchronizationHelper.SendNoticeForSuccessAsync(notifyArgs);
                    return syncInfo.ToId; ;
                }
                catch (Exception)
                {
                    if (notifyArgs.FromId != Guid.Empty)
                    {
                        await _synchronizationHelper.SendNoticeForFailAsync(notifyArgs);
                    }
                    throw;
                }
            }
        }

        [UnitOfWork]
        public Guid CreateOrUpdateContentCustomRouter(CustomRouterSyncDto input)
        {
            using (CurrentUnitOfWork.DisableFilter(
                AbpDataFilters.MayHaveTenant,
                AbpDataFilters.MustHaveTenant,
                MtSiteConsts.AbpDataFilters.MustHaveLanguage,
                AbpDataFilters.SoftDelete))
            {
                var args = new NoticeArgs();
                var syncInfo = ContentSyncHelper.CheckDataStatusForAutoSync(_contentRepository, _synchronizationHelper, 
                    input.ToTenantId, input.ToLanguage, input.FromContentId, args);
                if (syncInfo != null && syncInfo.ToId != Guid.Empty)
                {
                    _staticPageHelper.DeleteListAndDetailPage(input.ToTenantId, input.ToLanguage, syncInfo.ToMenuId, syncInfo.ToAuxiliaryId);
                    _synchronizationHelper.SyncRouteStr(input.FromContentId, syncInfo.ToId, input.ToTenantId, input.ToLanguage);
                    return syncInfo.ToId;
                }
                return Guid.Empty;
            }
        }

        public AutoSyncInfoStore CheckContentAndAutoSyncInfo(int targetTenantId, string targetLanguage, Guid fromCotnentId, NoticeArgs notify, bool isRequireSync = false)
        {
            if (isRequireSync)
            {
                return ContentSyncHelper.CheckDataStatusAndSyncForAutoSync(
                     _contentRepository, _synchronizationHelper, _contentDataSoreManager, _staticPageHelper,
                     targetTenantId, targetLanguage, fromCotnentId, notify);
            }
            else
            {
                return ContentSyncHelper.CheckDataStatusForAutoSync(_contentRepository, _synchronizationHelper,
                    targetTenantId, targetLanguage, fromCotnentId, notify);
            }
        }
    }
}
